package server;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import main.CommonMethods;
import main.Main;

import org.apache.log4j.Logger;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;

import tools.StringTools;
import utopiaintelpackage.BaseParser;
import botobjects.NewsItem;

import commandhandlers.NewsHandler;

public class JettyServer implements Runnable {

   private static class JettyNewsHandler extends AbstractHandler {
	  @Override
	  public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
			throws IOException, ServletException {
		 response.setContentType("text/html;charset=utf-8");
		 response.setStatus(HttpServletResponse.SC_OK);
		 baseRequest.setHandled(true);
		 String username = request.getParameter("username");
		 String password = request.getParameter("password");
		 String news = request.getParameter("news");
		 if (username == null || username.isEmpty() || password == null || password.isEmpty()) {
			response.getWriter().println("<form action=\"News\" method=\"post\" >");
			response.getWriter().println("Username: <input type=\"text\" name=\"username\" /><br />");
			response.getWriter().println("Password: <input type=\"password\" name=\"password\" /><br />");
			response.getWriter().println(
				  "News (one item per line): <br /><textarea rows=\"40\" cols=\"80\" name=\"news\"></textarea><br />");
			response.getWriter().println("<input type=\"submit\" />");
			response.getWriter().println("</form>");
		 } else if (news != null && !news.isEmpty()) {
			if (CommonMethods.loginBotAccount(username.trim(), password.trim())) {
			   String cleanedNews = news.replace("\r", "").trim();
			   String[] newsArray = cleanedNews.split("\n");
			   List<String> validNews = new ArrayList<String>(newsArray.length);
			   for (String newsItem : newsArray) {
				  if (NewsHandler.isNews(newsItem.trim()))
					 validNews.add(newsItem.trim());
			   }
			   boolean success = !validNews.isEmpty() && NewsItem.saveBatch(NewsHandler.parsePastedNews(validNews));
			   response.getWriter().println(success ? "Saved news successfully" : "Failed to save the news");
			} else {
			   response.getWriter().println("Your username/password are not valid");
			}
		 } else {
			response.getWriter().println("Username, password and actual news are all required");
		 }
	  }
   }

   private static class JettyIntelHandler extends AbstractHandler {
	  private static final String API_ENGINE_VERSION = "1";
	  private static final String MINIMUM_AGENT_VERSION = "20";
	  private static final String BULK_MODE = "true";

	  private static final String FORUM_AGENT_HEADER = "[FORUM AGENT API]";
	  private static final String INSTRUCTION_PREFIX = "FORUMAGENT:";

	  @Override
	  public void handle(final String target, final Request baseRequest, final HttpServletRequest request,
			final HttpServletResponse response) throws IOException, ServletException {
		 response.setContentType("text/html;charset=utf-8");
		 response.setStatus(HttpServletResponse.SC_OK);
		 baseRequest.setHandled(true);
		 String username = request.getParameter("username");
		 String password = request.getParameter("password");
		 if (username == null) {
			handShake(response);
		 } else {
			if (loginUser(username, password)) {
			   response.getWriter().println("+LOGIN");
			   response.getWriter().flush();
			   parseIntelAndPrintResponse(request, response, username);
			} else {
			   response.getWriter().println("-LOGIN");
			   response.getWriter().flush();
			}
		 }
	  }

	  private void handShake(final HttpServletResponse response) throws IOException {
		 response.getWriter().println(
			   FORUM_AGENT_HEADER + INSTRUCTION_PREFIX + "api_engine_version=\"" + API_ENGINE_VERSION + "\"" + INSTRUCTION_PREFIX
					 + "minimum_forum_agent_version=\"" + MINIMUM_AGENT_VERSION + "\"" + INSTRUCTION_PREFIX + "bulk_mode=\""
					 + BULK_MODE + "\"" + INSTRUCTION_PREFIX + "debug_mode=\"false\"");
		 response.getWriter().flush();
	  }

	  private boolean loginUser(final String username, final String password) {
		 return !StringTools.isNullOrEmpty(username) && !StringTools.isNullOrEmpty(password)
			   && CommonMethods.loginBotAccount(username, password);
	  }

	  private void parseIntelAndPrintResponse(final HttpServletRequest request, final HttpServletResponse response,
			final String username) throws IOException {
		 String data = request.getParameter("bulk_data") == null ? request.getParameter("data") : request
			   .getParameter("bulk_data");
		 List<String> intel = Arrays.asList(data.replace("\r", "").split("\n"));
		 for (final String s : BaseParser.INSTANCE.parseIntel(intel, username)) {
			response.getWriter().println(s + "\n");
			response.getWriter().flush();
		 }
	  }
   }

   @Override
   public void run() {
	  Server server = new Server(Main.getBotSettings().getIntelPort());

	  ContextHandlerCollection collection = new ContextHandlerCollection();

	  ContextHandler intelContext = new ContextHandler();
	  intelContext.setContextPath("/ForumAgent");
	  intelContext.setResourceBase(".");
	  intelContext.setClassLoader(Thread.currentThread().getContextClassLoader());
	  intelContext.setHandler(new JettyIntelHandler());

	  ContextHandler newsContext = new ContextHandler();
	  newsContext.setContextPath("/News");
	  newsContext.setResourceBase(".");
	  newsContext.setClassLoader(Thread.currentThread().getContextClassLoader());
	  newsContext.setHandler(new JettyNewsHandler());

	  collection.setHandlers(new Handler[] { intelContext, newsContext });
	  server.setHandler(collection);

	  try {
		 server.start();
		 server.join();
	  } catch (Exception e) {
		 Logger.getLogger("Error").error("", e);
	  }
   }
}
